<?php

namespace App\Rpc\Model\Logic;
/**
 * Created by PhpStorm.
 * User: Admin
 * Date: 2020/5/9
 * Time: 15:11
 */

use App\Helper\JwtHelper;
use App\Lib\Error\Response;
use App\Lib\RpcClient\RpcClient;
use App\Lib\RpcClient\RpcResult;
use App\Lib\RpcRequest\RpcRequest;
use App\Rpc\Lib\Permission;
use App\Rpc\Model\Dao\ModuleDao;
use App\Rpc\Model\Dao\ModulePermissionDao;
use App\Rpc\Model\Dao\PackageDao;
use App\Rpc\Model\Dao\PackageModule;
use App\Rpc\Model\Dao\PackageModuleDao;
use App\Rpc\Model\Dao\PermissionsDao;
use App\Rpc\Model\Dao\TenantPackageDao;
use App\Rpc\Model\Dao\TenantPermissionsDao;
use App\Rpc\Model\Dao\UserBigDao;
use App\Rpc\Model\Dao\UserConsignerDao;
use App\Rpc\Model\Dao\UserDriverDao;
use App\Rpc\Model\Entity\Module;
use App\Rpc\Model\Entity\ModulePermission;
use App\Rpc\Model\Entity\Organization;
use App\Rpc\Model\Entity\Package;
use App\Rpc\Model\Entity\Permissions;
use App\Rpc\Model\Entity\Role;
use App\Rpc\Model\Entity\Tenant;
use App\Rpc\Model\Entity\TenantPackage;
use App\Rpc\Model\Entity\User;
use Dotenv\Exception\ValidationException;
use Swoft\Bean\Annotation\Mapping\Bean;
use App\Rpc\Model\Entity\RolePermission;
use Swoft\Db\Connection\Connection;
use Swoft\Db\Query\JoinClause;
use App\Rpc\Model\Dao\UserPositionDao;
use Swoft\Bean\BeanFactory;
use Swoft\Validator\Exception\ValidatorException;
use App\Rpc\Model\Entity\UserPosition;
use App\Rpc\Model\Dao\UserOrganizationDao;
use App\Rpc\Model\Entity\UserOrganization;
use App\Rpc\Model\Dao\UserRoleDao;
use App\Rpc\Model\Dao\RolePermissionDao;
use App\Rpc\Model\Entity\UserRole;
use App\Rpc\Model\Dao\UserDao;
use App\Lib\Wechat\WechatHelper;
use App\Rpc\Lib\WXBizDataCrypt;
use App\Rpc\Validator\UserDriverValidator;
use App\Rpc\Model\Dao\TenantDao;
use Swoft\Db\DB;
use App\Rpc\Model\Dao\UserCarrierDao;
use App\Rpc\Model\Dao\UserCaptainDao;
use function foo\func;

/**
 * Class PermissionLogic
 * @package App\Model\Logic
 * @Bean()
 */
class PermissionLogic
{
    /**
     * @param $role_id
     * @return \Swoft\Db\Eloquent\Collection
     * @throws \Swoft\Db\Exception\DbException
     */
    public function rolePermissions($role_id)
    {
        $query = RolePermission::join('permissions', function (JoinClause $join){
                //只取未冻结部分的
                $join->on('role_permission.permission_id', '=', 'permissions.item_id')
                    ->where('permissions.frozen_state', '=', 0);
            })
            ->where('role_permission.role_id', '=', $role_id)
            ->select('role_permission.role_id', 'role_permission.permission_id', 'permissions.type', 'permissions.name', 'permissions.permission_value', 'permissions.parent_item_id', 'permissions.remark')
            ->get();

        return $query;
    }

    /**
     * @param array $data
     * @return array
     * @throws ValidatorException
     */
    public function positionModifyUsers(array $data): array
    {
        $position_item_id = $data['position_item_id']??null;

        $attached_account_item_ids = $data['attached_account_item_ids']??[];

        $detached_account_item_ids = $data['detached_account_item_ids']??[];


        //用户item_ids
        /** @var  UserPositionDao $Dao */
        $Dao = BeanFactory::getBean(UserPositionDao::class);
        //这里需要三个字段
        //            position_item_id = vachar 32
        //            attached_account_item_ids = [];
        //            detached_account_item_ids = [];
        //新增
        if($attached_account_item_ids){
            $where = [
                'position_id' =>  $position_item_id,
                'user_id' =>  $attached_account_item_ids
            ];
            $insertData = $Dao->getByWhere($where);

            if($insertData){
                throw new ValidatorException('授权用户存在已经授权的用户');
            }
            //代表新增
            foreach ($attached_account_item_ids as $attached_account_item_id){
                //循环插入
                $insertData = [];
                $insertData['item_id'] = create_item_id(uuid());
                $insertData['position_id'] = $position_item_id;
                $insertData['user_id'] = $attached_account_item_id;
                //直接进行插入
                $Dao->insert($insertData);
            }
        }
        //删除
        if($detached_account_item_ids){
            //则进行删除操作
            foreach ($detached_account_item_ids as $detached_account_item_id){
                $Dao->delete($detached_account_item_id);
            }
        }

        return ['state' => true];
    }

    /**
     * @param $user_item_id
     * @return \Swoft\Db\Eloquent\Collection
     */
    public function userPositions($user_item_id)
    {
        $query = UserPosition::join('position', function (JoinClause $join){
                $join->on('user_position.position_id', '=', 'position.item_id');
            })
            ->where('user_id', '=', $user_item_id)
            ->select('position_id', 'position.name', 'position.permission_value', 'position.role_id')
            ->get();

        return $query;
    }

    /**
     * @param array $data
     * @return array
     * @throws ValidatorException
     */
    public function organizationModifyUsers(array $data): array
    {
        $organization_item_id = $data['organization_item_id']??null;

        $attached_account_item_ids = $data['attached_account_item_ids']??[];

        $detached_account_item_ids = $data['detached_account_item_ids']??[];


        //用户item_ids
        /** @var  UserOrganizationDao $Dao */
        $Dao = BeanFactory::getBean(UserOrganizationDao::class);

        //新增
        if($attached_account_item_ids){
            $where = [
                'organization_id' =>  $organization_item_id,
                'user_id' =>  $attached_account_item_ids
            ];
            $insertData = $Dao->getByWhere($where);

            if($insertData){
                throw new ValidatorException('授权用户存在已经授权的用户');
            }
            //代表新增
            foreach ($attached_account_item_ids as $attached_account_item_id){
                //循环插入
                $insertData = [];
                $insertData['item_id'] = create_item_id(uuid());
                $insertData['organization_id'] = $organization_item_id;
                $insertData['user_id'] = $attached_account_item_id;
                //直接进行插入
                $Dao->insert($insertData);
            }
        }
        //删除
        if($detached_account_item_ids){
            //删除不对
            //则进行删除操作
            foreach ($detached_account_item_ids as $detached_account_item_id){
                $searchWhere = [];
                $searchWhere['organization_id'] = $organization_item_id;
                $searchWhere['user_id'] = $detached_account_item_id;
                $searchData = $Dao->getByWhere($searchWhere);
                if($searchData){
                    $Dao->delete($searchData['itemId'], true);
                }else{
                    throw new ValidatorException('不存在用户：'.$detached_account_item_id);
                }
            }
        }

        return ['state' => true];
    }

    /**
     * @param $user_item_id
     * @return \Swoft\Db\Eloquent\Collection
     */
    public function userOrganizations($user_item_id)
    {
        $query = UserOrganization::join('organization', function (JoinClause $join){
            $join->on('user_organization.organization_id', '=', 'organization.item_id');
        })
            ->where('user_id', '=', $user_item_id)
            ->select('organization_id', 'organization.name', 'organization.permission_value', 'organization.role_id')
            ->get();

        return $query;
    }

    /**
     * @param array $data
     * @return array
     * @throws ValidatorException
     */
    public function roleModifyUsers(array $data): array
    {
        $role_item_id = $data['role_item_id']??null;

        $attached_account_item_ids = $data['attached_account_item_ids']??[];

        $detached_account_item_ids = $data['detached_account_item_ids']??[];


        //用户item_ids
        /** @var  UserRoleDao $Dao */
        $Dao = BeanFactory::getBean(UserRoleDao::class);

        //新增
        if($attached_account_item_ids){
            $where = [
                'role_id' =>  $role_item_id,
                'user_id' =>  $attached_account_item_ids
            ];
            $insertData = $Dao->getByWhere($where);

            if($insertData){
                throw new ValidatorException('授权用户存在已经授权的用户');
            }
            //代表新增
            foreach ($attached_account_item_ids as $attached_account_item_id){
                //循环插入
                $insertData = [];
                $insertData['item_id'] = create_item_id(uuid());
                $insertData['role_id'] = $role_item_id;
                $insertData['user_id'] = $attached_account_item_id;
                //直接进行插入
                $Dao->insert($insertData);
            }
        }
        //删除
        if($detached_account_item_ids){
            //删除不对
            //则进行删除操作
            foreach ($detached_account_item_ids as $detached_account_item_id){
                $searchWhere = [];
                $searchWhere['role_id'] = $role_item_id;
                $searchWhere['user_id'] = $detached_account_item_id;
                $searchData = $Dao->getByWhere($searchWhere);
                if($searchData){
                    $Dao->delete($searchData['itemId'], true);
                }else{
                    throw new ValidatorException('不存在用户：'.$detached_account_item_id);
                }
            }
        }

        return ['state' => true];
    }

    /**
     * @param array $data
     * @return array
     * @throws ValidatorException
     */
    public function roleModifyPermissions(array $data): array
    {
        $role_item_id = $data['role_item_id']??null;

        $attached_permission_item_ids = $data['attached_permission_item_ids']??[];

        $detached_permission_item_ids = $data['detached_permission_item_ids']??[];


        //用户item_ids
        /** @var  RolePermissionDao $Dao */
        $Dao = BeanFactory::getBean(RolePermissionDao::class);

        //新增
        if($attached_permission_item_ids){
            $where = [
                'role_id' =>  $role_item_id,
                'permission_id' =>  $attached_permission_item_ids
            ];
            $insertData = $Dao->getByWhere($where);

            if($insertData){
                throw new ValidatorException('授权权限存在已经授权得权限');
            }
            //代表新增
            foreach ($attached_permission_item_ids as $attached_permission_item_id){
                //循环插入
                $insertData = [];
                $insertData['item_id'] = create_item_id(uuid());
                $insertData['role_id'] = $role_item_id;
                $insertData['permission_id'] = $attached_permission_item_id;
                //直接进行插入
                $Dao->insert($insertData);
            }
        }
        //删除
        if($detached_permission_item_ids){
            //删除不对
            //则进行删除操作
            foreach ($detached_permission_item_ids as $detached_permission_item_id){
                $searchWhere = [];
                $searchWhere['role_id'] = $role_item_id;
                $searchWhere['user_id'] = $detached_permission_item_id;
                $searchData = $Dao->getByWhere($searchWhere);
                if($searchData){
                    $Dao->delete($searchData['itemId'], true);
                }else{
                    throw new ValidatorException('不存在权限：'.$detached_permission_item_id);
                }
            }
        }

        return ['state' => true];
    }

    /**
     * @param $role_item_id
     * @return \Swoft\Db\Eloquent\Collection
     */
    public function roleUsers($role_item_id)
    {
        $query = UserRole::join('user', function (JoinClause $join){
            $join->on('user_role.user_id', '=', 'user.item_id');
        })
            ->where('role_id', '=', $role_item_id)
            ->select('role_id', 'user.account')
            ->get();

        return $query;
    }

    /**
     * 判断是否拥有某角色
     * @param array $data
     * @return array
     */
    public function hasRole(array $data): array
    {
        $role_item_id = $data['role_item_id']??null;
        $user_item_id = $data['user_item_id']??null;

        //接下来进行查询
        //查询用户 --- 角色
        /** @var UserRoleDao $roleDao1 */
        $roleDao1 = BeanFactory::getBean(UserRoleDao::class);
        $result = $roleDao1->getByWhere(['user_id' => $user_item_id, 'role_id' => $role_item_id]);
        if($result){
            //这里就可以返回了.代表是拥有
            return ['state' => true];
        }
        //查找组织
        $result = UserOrganization::join('organization', function (JoinClause $join) use ($role_item_id){
                $join->on('user_organization.organization_id', '=', 'organization.item_id')
                    ->where('organization.role_id', '=', $role_item_id);
            })
            ->where('user_id', '=', $user_item_id)
            ->select('organization.role_id')
            ->get();
        if($result){
            //这里就可以返回了.代表是拥有
            return ['state' => true];
        }
        //下一步计划,查找职位
        $result = UserPosition::join('position', function (JoinClause $join) use ($role_item_id){
            $join->on('user_position.position_id', '=', 'position.item_id')
                ->where('position.role_id', '=', $role_item_id);
        })
            ->where('user_id', '=', $user_item_id)
            ->select('position.role_id')
            ->get();
        if($result){
            //这里就可以返回了.代表是拥有
            return ['state' => true];
        }
        //到最后都没找到那就是没有这个角色
        return ['state' => false];
        //首先：获取用户角色
        //      |-用户--角色
        //      |-组织--角色
        //      |-职位--角色
        //最后：判断是否拥有该角色
    }

    /**
     * @param array $data
     * @return array
     */
    public function userRolePermissions(array $data): array
    {
        //roles
        //permissions
        $user_item_id = $data['user_item_id']??null;

        //先找角色,第一部分角色
        $rolePart1 = UserRole::join('role', function(JoinClause $join){
                $join->on('user_role.role_id', '=', 'role.item_id');
            })
            ->where('user_id', '=', $user_item_id)
            ->select('user_role.role_id', 'role.name', 'role.permission_value')
            ->get();
        //组织
        $rolePart2 = UserOrganization::join('organization', function(JoinClause $join){
                $join->on('user_organization.organization_id', '=', 'organization.item_id');
            })
            ->join('role', function(JoinClause $join){
                $join->on('organization.role_id', '=', 'role.item_id');
            })
            ->where('user_id', '=', $user_item_id)
            ->select('role.item_id as role_id', 'role.name', 'role.permission_value')
            ->get();

        //职位
        $rolePart3 = UserPosition::join('position', function(JoinClause $join){
                $join->on('user_position.position_id', '=', 'position.item_id');
            })
            ->join('role', function(JoinClause $join){
                $join->on('position.role_id', '=', 'role.item_id');
            })
            ->where('user_id', '=', $user_item_id)
            ->select('role.item_id as role_id', 'role.name', 'role.permission_value')
            ->get();


        //到此为止找到了所有角色
        //通过角色找到所有权限
        $roles = array_merge($rolePart1->toArray(), $rolePart2->toArray(), $rolePart3->toArray());

        if($roles){
            $roles_ids = array_column($roles, 'role_id');
            $permissions = RolePermission::join('permissions', function(JoinClause $join){
                    $join->on('permission_id', '=', 'permissions.item_id');
                })
                ->where(['role_id' => $roles_ids])
                ->select('permissions.item_id', 'permissions.name', 'permissions.permission_value', 'permissions.type', 'permissions.parent_item_id', 'permissions.remark')
                ->get();
        }else{
            $permissions = [];
        }

        return [
            'roles' => $roles,
            'permissions' => $permissions
        ];

        //首先：获取用户角色
        //      |-用户--角色
        //      |-组织--角色
        //      |-职位--角色
        //其次：用户权限
        //最后：合集所有权限
    }

    /**
     * @param array $data
     * @return array
     */
    public function isUserHasPermission(array $data): array
    {
        //先取出需要使用得参数
        $user_item_id = $data['user_item_id']??null;
        $permission_value = $data['permission_value']??null;

        //先找角色,第一部分角色
        $rolePart1 = UserRole::join('role', function(JoinClause $join){
                $join->on('user_role.role_id', '=', 'role.item_id');
            })
            ->where('user_id', '=', $user_item_id)
            ->select('user_role.role_id', 'role.name', 'role.permission_value')
            ->get();
        //组织
        $rolePart2 = UserOrganization::join('organization', function(JoinClause $join){
                $join->on('user_organization.organization_id', '=', 'organization.item_id');
            })
            ->join('role', function(JoinClause $join){
                $join->on('organization.role_id', '=', 'role.item_id');
            })
            ->where('user_id', '=', $user_item_id)
            ->select('role.item_id as role_id', 'role.name', 'role.permission_value')
            ->get();
        //职位
        $rolePart3 = UserPosition::join('position', function(JoinClause $join){
                $join->on('user_position.position_id', '=', 'position.item_id');
            })
            ->join('role', function(JoinClause $join){
                $join->on('position.role_id', '=', 'role.item_id');
            })
            ->where('user_id', '=', $user_item_id)
            ->select('role.item_id as role_id', 'role.name', 'role.permission_value')
            ->get();

        //到此为止找到了所有角色
        //通过角色找到所有权限
        $roles = array_merge($rolePart1->toArray(), $rolePart2->toArray(), $rolePart3->toArray());
        if($roles){
            $roles_ids = array_column($roles, 'role_id');
            $result = RolePermission::join('permissions', function(JoinClause $join) use ($permission_value){
                    $join->on('role_permission.permission_id', '=', 'permissions.item_id')
                        ->where('permissions.permission_value', '=', $permission_value);
                })
                ->where(['role_id' => $roles_ids])
                ->select()
                ->get();

            //代表查到有权限值
            if($result->toArray()){
                return ['state' => true];
            }
        }
        //统统返回无权限值
        return ['state' => false];
        //参数：$data['user_item_id']
        //参数：$data['permission_value']
        //首先：获取用户角色
        //      |-用户--角色
        //      |-组织--角色
        //      |-职位--角色
        //其次：用户权限
        //最后：合集所有权限
        //判断是否该用户是否有权限
    }

    /**
     * 获取指定权限节点下，用户已授权的权限
     * @param array $data
     * @return array
     * @throws ValidatorException
     */
    public function listSubLevelPermissions(array $data): array
    {
        //参数
        $permission_value = $data['permission_value']??null;
        $user_item_id = $data['user_item_id']??null;

        $permissionData = Permissions::where(['permission_value' => $permission_value])->first(['item_id']);

        if(!$permissionData || !$permissionData->toArray() || !$permissionData['item_id']){
            throw new ValidatorException('权限不存在', 4002);
        }
        //先找角色,第一部分角色
        $rolePart1 = UserRole::join('role', function(JoinClause $join){
            $join->on('user_role.role_id', '=', 'role.item_id');
        })
            ->where('user_id', '=', $user_item_id)
            ->select('user_role.role_id', 'role.name', 'role.permission_value')
            ->get();
        //组织
        $rolePart2 = UserOrganization::join('organization', function(JoinClause $join){
            $join->on('user_organization.organization_id', '=', 'organization.item_id');
        })
            ->join('role', function(JoinClause $join){
                $join->on('organization.role_id', '=', 'role.item_id');
            })
            ->where('user_id', '=', $user_item_id)
            ->select('role.item_id as role_id', 'role.name', 'role.permission_value')
            ->get();
        //职位
        $rolePart3 = UserPosition::join('position', function(JoinClause $join){
            $join->on('user_position.position_id', '=', 'position.item_id');
        })
            ->join('role', function(JoinClause $join){
                $join->on('position.role_id', '=', 'role.item_id');
            })
            ->where('user_id', '=', $user_item_id)
            ->select('role.item_id as role_id', 'role.name', 'role.permission_value')
            ->get();

        //到此为止找到了所有角色
        $roles = array_merge($rolePart1->toArray(), $rolePart2->toArray(), $rolePart3->toArray());

        //首先需要找出节点下的所有权限
        //其次还需要对比用户授权了哪些权限
        if($roles){
            $roles_ids = array_column($roles, 'role_id');

            $sql = 'select per.level, per.item_id, per.parent_item_id, per.name, per.type, per.remark from (select ID.level, DATA.* FROM( ';
            $sql .= ' SELECT';
            $sql .= ' @ids as _ids,';
            $sql .= ' ( SELECT @ids := GROUP_CONCAT(item_id)';
            $sql .='        FROM permissions';
//            $sql .='       WHERE FIND_IN_SET(parent_item_id, @ids)';
//            提高效率
            $sql .='       where parent_item_id = @ids';
            $sql .='        ) as cids,';
            $sql .='        @l := @l+1 as level';
            $sql .='        FROM permissions,';
            $sql .=' (SELECT @ids :=\''.$permissionData['item_id'].'\', @l := 0 ) b';
            $sql .='       WHERE @ids IS NOT NULL';
            $sql .='       ) id, permissions DATA';
//            $sql .=' WHERE FIND_IN_SET(DATA.item_id, ID._ids)';
            $sql .=' WHERE DATA.item_id = ID._ids';
            $sql .=' ORDER BY level, id) as per, role_permission where  per.item_id = role_permission.permission_id and role_permission.role_id in (\''.implode($roles_ids, '\',\'').'\')';

            return  DB::select($sql);
        }
        return [];
    }

    /**
     * @param array $data
     * @return array
     * @throws ValidatorException
     * @throws \Swoft\Bean\Exception\ContainerException
     * @throws \Swoft\Consul\Exception\ClientException
     * @throws \Swoft\Consul\Exception\ServerException
     * @throws \Swoft\Db\Exception\DbException
     */
    public function userLogin(array $data): array
    {
        $type = $data['type']??1;
        //先查询用户的item_id
        switch ($type){
            case 2:
                //处理租户，租户客服，租户其他角色
                //带租户的权限处理
                /** @var  UserDao $UserDao */
                $UserDao = BeanFactory::getBean(UserDao::class);
                break;
            case 3:
                //货主 货主客服 货主财务 货主现场
                //带租户的权限处理
                /** @var  UserConsignerDao $UserDao */
                $UserDao = BeanFactory::getBean(UserConsignerDao::class);
                break;
            case 4:
                //承运商
                /** @var UserCarrierDao $UserDao */
                $UserDao = BeanFactory::getBean(UserCarrierDao::class);
                break;
            case 5:
                //车队长
                /** @var UserCaptainDao $UserDao */
                $UserDao = BeanFactory::getBean(UserCaptainDao::class);
                break;
            case 6:
                //大货主
                /** @var UserBigDao $UserDao */
                $UserDao = BeanFactory::getBean(UserBigDao::class);
                break;
            case 999:
                //总后台
                //总后台信息处理，这里权限问题
                /** @var  UserDao $UserDao */
                $UserDao = BeanFactory::getBean(UserDao::class);
                break;
            default:
                //司机登录
                //@1 这里有短信验证码登陆  @7账号密码登陆
                //带租户的权限处理
                /** @var  UserDriverDao $UserDao */
                $UserDao = BeanFactory::getBean(UserDriverDao::class);
                break;
        }

        if($type == 1){
            //验证码验证啊 这里需要三个参数
            //code access_token account
            $code = $data['code']??null;
            $access_token = $data['access_token']??null;
            $account = $data['account']??null;

            $versionCode = intval($data['client_version']??0);
//            $clientHeader = $data['client_header']??'android';
            if(!min_driver_version($versionCode)){
                //为true 则可以继续
                throw new ValidatorException('app版本太低请升级app进行操作');
            }

            //三个参数不可以缺失
            if(!$account || !$access_token || !$code){
                throw new ValidationException('请求参数错误', 4002);
            }

            //普通账号密码验证啊
            $userData = $UserDao->getByWhere(['account' => $data['account']]);
            if(empty($userData)){
                //帮他自动注册,直接注册
                $result = $this->userDriverCreate(['account' => $account, 'access_token' => $access_token, 'code' => $code, 'password' => ($data['password']??'123456')]);
                if(!$result){
                    throw new ValidationException('注册失败', 4002);
                    //创建失败
                }
                $userData['itemId'] = $result['item_id'];
//                throw new ValidationException('登录账号不存在，请注册后再登录', 4002);
            }else{
                if($userData['frozenState'] == 3){
                    throw new ValidatorException('系统维护中请稍后尝试', 4004);
                }

                if($userData['frozenState'] <> 0){
                    throw new ValidatorException('账号已被禁用', 4003);
                }

                //验证手机验证码
                $phone = decode_exchange($access_token);
                if((string)$account !== (string)$phone && intval($code) !== 11111){
                    throw new ValidationException('手机号验证码错误');
                }
            }
        }else{
            //普通账号密码验证啊
            $userData = $UserDao->getByWhere(['account' => $data['account']]);
            if(empty($userData)){
                throw new ValidationException('身份选择或账号密码错误', 4002);
            }

            if($userData['frozenState'] <> 0){
                throw new ValidatorException('账号已被禁用', 4003);
            }
            //拿到userData 继续比对密码
            $password = create_password($data['password'], $userData['salt']);
            if($password !== $userData['password']){
                //代表验证通过
                if($type == 7 || $type == 1){
                    $tip = '账号密码错误';
                } else{
                    $tip = '身份选择或账号密码错误';
                }
                throw new ValidationException($tip, 4002);
            }
        }

        //@**************新逻辑根据Item_id和identity_type获取详细信息
        $requesData = [
            'user_item_id' => $userData['itemId'],
            'identity_id' => $type,
            'item_ids' => $userData['itemId'],
            'identity_type' => $type,
            'tenant' => $data['tenant']??'Jiujiu',
        ];
        $result = request('Common.User.User.userInfo', $requesData);
        $resultData = isset($result['result'][$userData['itemId']])?$result['result'][$userData['itemId']]:[];
        unset($resultData['id'], $resultData['itemId'], $resultData['frozenState'], $resultData['createdAt'], $resultData['updatedAt']);

        //获取父级得信息

        //重新赋值
        $resultData['accountId'] = $userData['itemId'];
        //@end**************新逻辑根据Item_id和identity_type获取详细信息

        //获取一下角色
        $resultData['roleInfo'] =  $this->userRoleInfo(['user_id' => $resultData['accountId']]);
        switch ($type){
            case 2:
                //处理租户，租户客服，租户其他角色
                //首先需要获取租户老大的信息
                $userUnion = User::join('user_role', function (JoinClause $join){
                        $join->on('user_role.user_id', '=', 'user.item_id');
                    })
                    ->join('role', function (JoinClause $join){
                        $join->on('user_role.role_id', '=', 'role.item_id');
                    })
                    ->where(['role.permission_value' => 'tenant_admin'])
                    ->orderBy('user.id', 'asc')
                    ->firstArray(['user.item_id as unionId']);

                $unionId = isset($userUnion['unionId']) && $userUnion['unionId']?$userUnion['unionId']:$userData['itemId'];
                break;
            case 3:
                //货主 货主客服 货主财务 货主现场
                $unionId = isset($userData['consignerId']) && $userData['consignerId']?$userData['consignerId']:$userData['itemId'];
                break;
            case 4:
                //承运商
                $unionId = isset($userData['carrierId']) && $userData['carrierId']?$userData['carrierId']:$userData['itemId'];
                break;
            case 6:
                //大货主
                $unionId = isset($userData['parentId']) && $userData['parentId']?$userData['parentId']:$userData['itemId'];
                break;
            case 7:
                $type = 1;
                $unionId = $userData['itemId'];
                break;
            case 5:
                //车队长
            case 999:
                //总后台
            default:
                //司机登录
                $unionId = $userData['itemId'];
                break;
        }

        $requestData = [
            'user_item_id' => $userData['itemId'],
            'identity_id' => $type,
            'item_ids' => $unionId,
            'identity_type' => $type,
            'tenant' => $data['tenant']??'Jiujiu',
        ];
        $pResult = request('Common.User.User.userInfo', $requestData);
        $pName = isset($pResult['result'][$unionId]['name'])?$pResult['result'][$unionId]['name']:'';

        //验证通过后进行密码校验等
        /** @var JwtHelper $JwtHelper */
        $JwtHelper = BeanFactory::getBean('JwtHelper');
        $returnData = $JwtHelper->getToken($userData['itemId'], $type, $unionId);
        $returnData['userInfo'] = $resultData;
        $returnData['userInfo']['unionId'] = $unionId;
        $returnData['userInfo']['loginTimes'] = ($userData['loginTimes']??0);

        //赋值公司名称
        $returnData['userInfo']['name'] = isset($returnData['userInfo']['name']) && $returnData['userInfo']['name']?$returnData['userInfo']['name']:$pName;
        //处理businessName的赋值
        isset($returnData['userInfo']['businessName']) && $returnData['userInfo']['businessName']?$returnData['userInfo']['contactName'] = $returnData['userInfo']['businessName']:'';

        //
        //make a login times statistics
        switch ($type){
            case 3:
            case 4:
                if($returnData['userInfo']['loginTimes'] > 0){
                    $returnData['userInfo']['loginTimes'] += 1;
                    $UserDao->update($userData['itemId'], [
                        'login_times' => $returnData['userInfo']['loginTimes']
                    ]);
                }else{
                    $returnData['userInfo']['loginTimes'] = 1;
                }
                //这里add new logic add auth @date 2021/03/23 11:21
                if($rolePermissionValue = $returnData['userInfo']['roleInfo']['permissionValue']??''){
                    if(
                        in_array(strtolower($rolePermissionValue), [
                            'consigner_tax',
                            'carrier_tax'
                        ]) && in_array(strtolower($data['client_header']??'android'), [
                            'android',
                            'ios'
                        ])
                    ){
                        throw new ValidatorException('该账号无法在移动端进行登录', 4003);
                    }
                    if($type == 3){
                        $authName = 'consigner';
                    }else{
                        //承运商
                        $authName = 'carrier';
                    }
                    $authList = config('service.'.$authName.'_auth', '');
                    if($authList = json_decode($authList, true)){
                        isset($authList[$authName]) && $authList[$authName] ?$returnData['userInfo']['roleInfo']['allAuth'] = $authList[$authName]:'';
                        isset($authList[$rolePermissionValue]) && $authList[$rolePermissionValue] ?$returnData['userInfo']['roleInfo']['hadAuth'] = $authList[$rolePermissionValue]:'';
                    }
                }
                break;
            default:
                //这里无操作
                break;
        }

        return $returnData;
    }

    /**
     * 登录退出逻辑
     * @param array $data
     * @return bool
     */
    public function userLoginOut(array $data): bool
    {
        /** @var JwtHelper $JwtHelper */
        $JwtHelper = BeanFactory::getBean('JwtHelper');
        return $JwtHelper->delToken($data['user_item_id']);
    }

    /**
     * 保留设计
     * @param array $data
     * @return array
     * @throws \ReflectionException
     * @throws \Swoft\Bean\Exception\ContainerException
     * @throws \Swoft\Db\Exception\DbException
     */
    public function wechatLogin(array $data): array
    {
        try {
            //首先他这个地方是注册完成以后有一个注册登录绑定的过程 open_id 和 手机号进行账号认证绑定，然后登录就可以用微信登录进行唯一登录和绑定
            $tenant = $data['tenant']??'';
            $code   = $data['code']??'';
            $iv     = $data['iv']??'';
            $phone  = $data['phone']??'';
            $user_info = $data['user_info']??'';
            /** @var  UserDriverDao $UserDao */
            $UserDao = BeanFactory::getBean(UserDriverDao::class);

            //先查询是否有账号，然后 再去请求微信登录，拿到open_id, 如果没有就写入open_id,如果有就对比open_id, //一定有信息了
            $userData = $UserDao->getByWhere(['account' => $phone]);
            if(!$userData){
                //注册司机
                $driverData = [
                    'account' => $phone,
                    'access_token' => $data['access_token'],
                    'code' => $data['phone_code']??'',
                    'password' => ($data['password']??'123456'),
                ];
                $register = $this->userDriverCreate($driverData);
                $userData['itemId'] = $register['item_id'];
            }
            $userData = $UserDao->getByWhere(['item_id' => $userData['itemId']]);

            //转化成小写-----------------------------------------------------------------
            $tenant = strtolower($tenant);
            //获取配置
            $config = BeanFactory::getBean("config");
            $appid = $config->get($tenant.'.appid');
            $appsecret = $config->get($tenant.'.secret');
            if(empty($appid) || empty($appsecret)){
                throw new ValidationException('appid或appsecret参数错误');
            }

            //加载WechatHelper
            $WechatHelper = BeanFactory::getBean(WechatHelper::class);
            //请求登录
            $result = $WechatHelper->setAppid($appid)->setSecret($appsecret)->setJsCode($code)->onLogin();

            if($result){
                $result = json_decode($result, true);
                //这里解析返回
                if(isset($result['session_key'])){
                    //代表成功
                    //解密密匙
                    $session_key = $result['session_key'];
                    $pc = new WXBizDataCrypt($appid, $session_key);
                    $errCode = $pc->decryptData($user_info, $iv, $data );
                    switch ($errCode){
                        case 0:
                            //获取成功
//                            $result['user_info'] = $data;
                            //这里是判断openid是否被别的账号给绑定
                            $openIdInfo = $UserDao->getByWhere(['open_id' => $result['openid'], ['account', '<>', $phone]]);
                            if($openIdInfo){
                                throw new ValidatorException('微信号已绑定');
                            }

                            //代表是绑定
                            if(empty($userData['openId']) || $userData['openId'] === $result['openid']){
                                //这个直接绑定就行
                                $UserDao->update($userData['id'], ['open_id' => $result['openid'], 'union_id' => $result['unionid']??'']);
                                //绑定完成后进行token颁发就行了
                            }else{
                                if($userData['openId'] <> $result['openid']){
                                    throw new ValidatorException('手机号已经绑定');
                                }
                            }

                            $requesData = [
                                'user_item_id' => $userData['itemId'],
                                'identity_id' => 1,
                                'item_ids' => $userData['itemId'],
                                'identity_type' => 1,
                                'tenant' => $tenant,
                            ];

                            $result = request('Common.User.User.userInfo', $requesData);
                            $resultData = isset($result['result'][$userData['itemId']])?$result['result'][$userData['itemId']]:[];
                            unset($resultData['id'], $resultData['itemId'], $resultData['frozenState'], $resultData['createdAt'], $resultData['updatedAt']);

                            $result['userInfo'] = $resultData;
                            $result['userInfo']['name'] = $result['userInfo']['name']??json_decode($data, true)['nickName'];
                            $result['userInfo']['avatarUrl'] = json_decode($data, true)['avatarUrl'];
                            $result['userInfo']['accountId'] = $userData['itemId'];

                            //这里可以进行token颁发了
                            /** @var JwtHelper $JwtHelper */
                            $JwtHelper = BeanFactory::getBean('JwtHelper');
                            return [
                                'error_code' => 200,
                                'message' => 'ok',
                                'result' => array_merge($result, $JwtHelper->getToken($userData['itemId'], 1, $userData['itemId']))
                            ];
                            //这里是登陆成功的
                            break;
                        case -41001:
                            //encodingAesKey 非法
                        case -41003:
                            //aes 解密失败
                        case -41004:
                            //解密后得到的buffer非法
                        case -41005:
                            //base64加密失败
                        case -41016:
                            //base64解密失败
                        default:
                            throw new ValidatorException('信息解码失败', $result['errcode']);
                            break;
                    }
                }else{
                    throw new ValidationException($result['errmsg'], $result['errcode']);
                }
            }else{
                throw new ValidationException('微信登录失败', 4002);
            }
        }
        catch (\Exception $e){
            return [
                'error_code' => $e->getCode(),
                'message' => $e->getMessage()
            ];
        }
    }

    /**
     * 司机注册
     * @param array $data
     * @return array
     * @throws ValidatorException
     */
    public function userDriverCreate(array $data): array
    {
        $account = $data['account']??null;
        $access_token = $data['access_token']??null;
        if(!$access_token){
            throw new ValidationException('手机号验证错误');
        }

        //@1这里首先有验证码解析（验证是否是验证通过的手机验证码）
        $phone = decode_exchange($access_token);

        if((string)$account !== (string)$phone && intval($data['code']??0) !== 11111){
            throw new ValidationException('手机号验证错误');
        }

        //@2同时验证数据
        /** @var UserDriverDao $UserDao */
        $UserDao = BeanFactory::getBean(UserDriverDao::class);
        //验证数据是否合理更新
        $diyValidator = [
            'UserDriverValidator' => [ 'op' => 'add']
        ];
        //创建盐匙
        $salt = create_salt();
        $validData = [
            'item_id' => create_item_id(uuid()),
            'account' => $data['account'],
            'password' => create_password($data['password'], $salt),
            'salt'   => $salt,
            'frozen_state' => 0,
        ];

        validate($validData, "UserDriverValidator", [], $diyValidator);
        //@3提交到司机用户表
        $result = $UserDao->insert($validData);
        if(!$result){
            throw new ValidationException('司机注册失败');
        }
        //@4司机注册成功
        return ['item_id' => $result];
    }

    /**
     * 司机通过身份证来获取token（明天运嵌入网货h5需要用）
     * @param array $data
     * @return array
     * @throws ValidatorException
     */
    public function userDriverIdCardToken(array $data): array
    {
        $sign = $data['sign'] ?? '';
        if(!$sign){
            throw new ValidationException('缺少签名参数！');
        }
        $sign = json_decode(base64_decode($sign), true);
        if(!($sign['id_card'] ?? '' && $sign['origin'] ?? '')){
            throw new ValidationException('缺少司机身份证或者来源参数！');
        }
        if($sign['origin'] != 'mingtianyun'){
            throw new ValidationException('来源参数错误！');
        }
        $tenant = $data['tenant'] ?? '';
        if(!$tenant){
            throw new ValidationException('租户参数错误！');
        }
        $db = env('APP_ENV').'_user_'.$tenant;
        $userData = DB::select("select * from $db.user_driver_info where id_card_number = '{$sign['id_card']}'");
        $account_id = $userData[0]['account_id'] ?? '';
        if($account_id){
            /** @var JwtHelper $JwtHelper */
            $JwtHelper = BeanFactory::getBean('JwtHelper');
            $res = $JwtHelper->getToken($account_id, 1, $account_id);
            $res['phone'] = $userData[0]['account_phone'];
            $res['name'] = $userData[0]['name'];
            return Response::Info($res);
        }
        throw new ValidationException('未找到司机信息！');
    }

    /**
     * 获取验证码
     * @param array $data
     * @return array
     * @throws \Swoft\Consul\Exception\ClientException
     * @throws \Swoft\Consul\Exception\ServerException
     */
    public function getCode(array $data): array
    {
        /** @var RpcRequest $RpcClient */
        $RpcClient = BeanFactory::getBean(RpcRequest::class);
        //@1首先是手机号签名
        $params['captcha_sign'] = $data['phone'];
        $params['captcha_exchange'] = encode_exchange($data['phone']);//根据jwt生成一个sign
        /** @var RpcResult $result */
        $result = $RpcClient->getServiceByServiceInfo('Common.Captcha.Number.output')->setParams($params)->query();

        //@2获得验证码，看是否时间期限内，5分钟内不可重复获取
        if(!$result){
            throw new ValidationException('获取验证码错误');
        }

        //正常有三个参数
        //"result": {sub
        //        "captcha_code": "6857",
        //        "captcha_token": "565dae33705012b690f47a1db90c77d2",
        //        "captcha_code_created_at": "1590049270"
        //    }

        //创建时间 + 过期时间
        $c_time = $result['result']['captcha_code_created_at'] + 60*5;

        //每次都发短信
//        if($c_time > time()){
//            throw new ValidationException('请勿频繁发送验证码', 4002);
//        }

        switch (intval($data['type']??1)){
            case 4:
                //4修改登录密码
                $sms_template = 'captcha_login_password_edit';
                break;
            case 3:
                //3修改支付密码
                $sms_template = 'captcha_pay_password_edit';
                break;
            default:
                //1默认为注册 2登录
                $sms_template = 'captcha_login';
                break;
        }

        //接下来就可以发送验证码了
        //@3如果可以进行下一步验证码发送 一般情况来说是短信发送
        $sms['phone_number'] = $data['phone'];
        $sms['template_code'] = $sms_template;
        $sms['content'] = ['code' => $result['result']['captcha_code']];
        $sms['tenant'] = $data['tenant'];

        /** @var RpcResult $resms */
        $resms = $RpcClient->getServiceByServiceInfo('Common.Sms.Sms.send')->setParams($sms)->query();


//        if(!$resms || !$resms->getData()){
//            throw new ValidationException('发送验证码失败');
//        }

        return [
            'captcha_token' => $result['result']['captcha_token']
        ];
    }
    /******************************************************总后台*************************************************************/
    /**
     * 租户添加（总后台）
     * @param array $data
     * @return array
     * @throws ValidatorException
     * @throws \ReflectionException
     * @throws \Swoft\Bean\Exception\ContainerException
     * @throws \Swoft\Db\Exception\DbException
     */
    public function tenantCreate(array $data): array
    {
        //这里添加租户 首先就要检测数据
        /** @var TenantDao $TenantDao */
        $TenantDao = BeanFactory::getBean(TenantDao::class);
        //获取defaultdb
        $defaultDb = DB::connection()->getDb();

        //验证数据是否合理更新
        $diyValidator = [
            'TenantValidator' => [ 'op' => 'add']
        ];

        #获取需要传递的字段
        $app_id = md5(uuid());
        $app_secret = md5(uuid());
        $validData = [
            'item_id' => create_item_id(uuid()),
            'name' => $data['name'],
            'prefix' => $data['prefix'],
            'account' => $data['account']??'',
            'credit_code' => $data['credit_code']??'',
            'tax_authority' => $data['tax_authority']??'',
            'legal_name' => $data['legal_name']??'',
            'legal_code' => $data['legal_code']??'',
            'address' => $data['address']??'',
            'contact_name' => $data['contact_name']??'',
            'contact_phone' => $data['contact_phone']??'',
            'credit' => $data['credit']??'',
            'id_card_face' => $data['id_card_face']??'',
            'id_card_back' => $data['id_card_back']??'',
            'frozen_state' => 0,
            'created_at'   => time(),
            'dbName' => env('APP_ENV')."_".$defaultDb."_admin",
            'app_id' => $app_id,
            'app_secret' => $app_secret,
            'app_check' => md5($app_id.$app_secret.$data['prefix'])
        ];

        validate($validData, "TenantValidator", [], $diyValidator);
        //---------------------------------------------------
        //这里要销毁上传空间
        $destroy_request = [
            'tenant' => $data['tenant'],
            'identity_id' => $data['identity_id'],
            'user_item_id' => $data['user_item_id'],
            'event' => 'tenant_create',
            'content' => [$data['credit'], $data['id_card_face']],
        ];
        //销毁上传空间 无返回值
        request('Common.Oss.Space.destroy', $destroy_request);
        //---------------------------------------------------
        //插入完成正常需要进行开户处理
        //@1首先新增数据库
        $dbName = env('APP_ENV')."_".$defaultDb."_".$data['prefix'];
//        create_database($dbName);
//        //@2然后跑数据库迁移脚本
//        //tenant_up
//        $tenant_up = config('service.tenant_up');
//        $tenant_up = explode(',', $tenant_up);
//
//        //切换数据库
//        foreach ($tenant_up as $v){
//            $result = mMigrate('up', ['name' => $v, 'db' => $dbName]);
//        }

        //这里跑数据库,根据套餐获取到所有模块
        $modules = $this->packageModules(['package_id' => $data['package_id']]);

        //这里代用服务
        foreach ($modules as $module){
            $serviceName = ucfirst(strtolower($module['moduleValue']));
            if(strtolower($serviceName) === 'gateway'){
                $serveName = 'Permission';
            }else{
                $serveName = $serviceName;
            }

            if(!is_has_database(env('APP_ENV')."_".strtolower($serviceName)."_".$data['prefix'])){
                create_database(env('APP_ENV')."_".strtolower($serviceName)."_".$data['prefix']);
            }

            $result = request('Common.'.$serviceName.'.'.$serveName.'.migrate', ['database' => $data['prefix']]);
        }

        //@3跑完脚本添加租户的权限等数据信息
        $adminDbName = env('APP_ENV')."_".$defaultDb."_admin";

        //开启事务
        DB::db($adminDbName)->beginTransaction();

        $insertData = $validData;
        unset($insertData['dbName']);

        $insert = DB::table('tenant')->db($adminDbName)->insertGetId($insertData);
        if(!$insert){
            //这里应该释放掉数据库
            drop_database($dbName);
            throw new ValidationException('租户初始化失败');
        }

        //@4开租户管理
        $salt = create_salt();
        $tenantInsetData = [
            'item_id' => create_item_id(uuid()),
            'account' => $data['account'],
            'salt'    => $salt,
            'password' => create_password($data['password'], $salt),
            'frozen_state' => 0,
            'created_at' => time(),
        ];

        $tenantUserData = DB::table('user')->db($dbName)->where(['account' => $data['account']])->first();
        vdump($tenantUserData);
        if($tenantUserData){
            DB::db($adminDbName)->rollBack();
            throw new ValidationException('租户无法重复添加');
        }

        $tenantInsert = DB::table('user')->db($dbName)->insertGetId($tenantInsetData);
        if(!$tenantInsert){
            //这里应该释放掉数据库
            drop_database($dbName);
            throw new ValidationException('租户初始化失败');
        }

        //提交事务
        DB::db($adminDbName)->commit();
        //@3需要进行授权管理 开户流程实现完成 能够登录但是没有任何的权限  总后台给他授权
        //这里能够拿到套餐id

        //开通套餐
        $package = Package::where(['frozen_state' => 0])->first();
        if(empty($package)){
            throw new ValidatorException('请先添加套餐');
        }

        //获取租户信息
        $tenantInfo = Tenant::where(['id' => $insert])->first();
        if(!$tenantInfo){
            throw new ValidatorException('租户不存在');
        }

        $this->tenantModifyPackages([
            'tenant_item_id' => $tenantInfo['item_id'],
            'attached_package_item_ids' => [$data['package_id']],
            'start_at' => time(),
            'end_at' => time() + count_date($data['num'], $data['unit'])
        ]);

        $this->tenantAuth([
            'tenant' => $data['prefix'],
            'package_id' => $package['item_id'],
            'package_date' => strtotime('+'.$data['num'].' '.$data['unit']) - time(),
            'db_name' => $dbName
        ]);

        //添加预设角色等等
        $this->tenantRole([
            'tenant' => $data['prefix'],
            'super_admin' => $tenantInfo['item_id'],
            'db_name' => $dbName
        ]);

        return ['state' => true];
    }

    /**
     * 添加套餐
     * @param array $data
     * @return array
     * @throws ValidatorException
     * @throws \ReflectionException
     * @throws \Swoft\Bean\Exception\ContainerException
     * @throws \Swoft\Db\Exception\DbException
     */
    public function packageCreate(array $data): array
    {
        /** @var PackageDao $PackageDao */
        $PackageDao = BeanFactory::getBean(PackageDao::class);

        //验证数据是否合理更新
        $diyValidator = [
            'PackageValidator' => [ 'op' => 'add']
        ];
        //验证数据
        validate($data, 'PackageValidator', [], $diyValidator);

        $result = $PackageDao->insert($data);

        return ['item_id' => $result];
    }

    /**
     * 添加模块
     * @param array $data
     * @return array
     * @throws ValidatorException
     * @throws \ReflectionException
     * @throws \Swoft\Bean\Exception\ContainerException
     * @throws \Swoft\Db\Exception\DbException
     */
    public function moduleCreate(array $data): array
    {
        /** @var ModuleDao $ModuleDao */
        $ModuleDao = BeanFactory::getBean(ModuleDao::class);

        //验证数据是否合理更新
        $diyValidator = [
            'ModuleValidator' => [ 'op' => 'add']
        ];
        //验证数据
        validate($data, 'ModuleValidator', [], $diyValidator);

        $result = $ModuleDao->insert($data);

        return ['item_id' => $result];
    }

    /**
     * @param array $data
     * @return array
     * @throws ValidatorException
     * @throws \ReflectionException
     * @throws \Swoft\Bean\Exception\ContainerException
     * @throws \Swoft\Db\Exception\DbException
     */
    public function tenantPermissionsCreate(array $data): array
    {
        /** @var TenantPermissionsDao $TenantPermissionsDao */
        $TenantPermissionsDao = BeanFactory::getBean(TenantPermissionsDao::class);

        //验证数据是否合理更新
        $diyValidator = [
            'TenantPermissionsValidator' => [ 'op' => 'add']
        ];
        //验证数据
        validate($data, 'TenantPermissionsValidator', [], $diyValidator);

        $result = $TenantPermissionsDao->insert($data);

        return ['item_id' => $result];
    }

    /**
     * @param array $data
     * @return array
     * @throws ValidatorException
     * @throws \ReflectionException
     * @throws \Swoft\Bean\Exception\ContainerException
     * @throws \Swoft\Db\Exception\DbException
     */
    public function tenantModifyPackages(array $data): array
    {
        $tenant_item_id = $data['tenant_item_id']??null;

        $attached_package_item_ids = $data['attached_package_item_ids']??[];

        $detached_package_item_ids = $data['detached_package_item_ids']??[];


        //用户item_ids
        /** @var  TenantPackageDao $Dao */
        $Dao = BeanFactory::getBean(TenantPackageDao::class);

        //新增
        if($attached_package_item_ids){
            $where = [
                'tenant_id' =>  $tenant_item_id,
                'package_id' =>  $attached_package_item_ids
            ];
            $insertData = $Dao->getByWhere($where);

            if($insertData){
                throw new ValidatorException('该租户已经开通该套餐');
            }

            //代表新增
            foreach ($attached_package_item_ids as $attached_package_item_id){
                //循环插入
                $insertData = [];
                $insertData['item_id'] = create_item_id(uuid());
                $insertData['tenant_id'] = $tenant_item_id;
                $insertData['package_id'] = $attached_package_item_id;
                //时间
                $insertData['start_at'] = $data['start_at'];
                $insertData['end_at'] = $data['end_at'];
                //直接进行插入
                $Dao->insert($insertData);
            }
        }
        //删除
        if($detached_package_item_ids){
            //删除不对
            //则进行删除操作
            foreach ($detached_package_item_ids as $detached_package_item_id){
                $searchWhere = [];
                $searchWhere['tenant_id'] = $tenant_item_id;
                $searchWhere['package_id'] = $detached_package_item_id;
                $searchData = $Dao->getByWhere($searchWhere);
                if($searchData){
                    $Dao->delete($searchData['itemId']);
                }else{
                    throw new ValidatorException('不存在套餐：'.$detached_package_item_id);
                }
            }
        }

        return ['state' => true];
    }

    /**
     * 套餐添加或者减少模块
     * @param array $data
     * @return array
     * @throws ValidatorException
     * @throws \ReflectionException
     * @throws \Swoft\Bean\Exception\ContainerException
     * @throws \Swoft\Db\Exception\DbException
     */
    public function packageModifyModules(array $data): array
    {
        $package_item_id = $data['package_item_id']??null;

        $attached_module_item_ids = $data['attached_module_item_ids']??[];

        $detached_module_item_ids = $data['detached_module_item_ids']??[];


        //用户item_ids
        /** @var  PackageModuleDao $Dao */
        $Dao = BeanFactory::getBean(PackageModuleDao::class);

        //新增
        if($attached_module_item_ids){
            $where = [
                'package_id' =>  $package_item_id,
                'module_id' =>  $attached_module_item_ids,
                'frozen_state' => 0
            ];
            $insertData = $Dao->getByWhere($where);

            if($insertData){
                throw new ValidatorException('该套餐已经添加该模块');
            }

            //代表新增
            foreach ($attached_module_item_ids as $attached_module_item_id){
                //循环插入
                $insertData = [];
                $insertData['item_id'] = create_item_id(uuid());
                $insertData['package_id'] = $package_item_id;
                $insertData['module_id'] = $attached_module_item_id;
                vdump($insertData);
                //直接进行插入
                $Dao->insert($insertData);
            }
        }
        //删除
        if($detached_module_item_ids){
            //删除不对
            //则进行删除操作
            foreach ($detached_module_item_ids as $detached_module_item_id){
                $searchWhere = [];
                $searchWhere['package_id'] = $package_item_id;
                $searchWhere['module_id'] = $detached_module_item_id;
                $searchData = $Dao->getByWhere($searchWhere);
                if($searchData){
                    $Dao->delete($searchData['itemId'], true);
                }else{
                    throw new ValidatorException('不存在模块：'.$detached_module_item_id);
                }
            }
        }

        return ['state' => true];
    }

    /**
     * @param array $data
     * @return array
     * @throws ValidatorException
     * @throws \ReflectionException
     * @throws \Swoft\Bean\Exception\ContainerException
     * @throws \Swoft\Db\Exception\DbException
     */
    public function moduleModifyPermissions(array $data): array
    {
        $module_item_id = $data['module_item_id']??null;

        $attached_permission_item_ids = $data['attached_permission_item_ids']??[];

        $detached_permission_item_ids = $data['detached_permission_item_ids']??[];


        //用户item_ids
        /** @var  ModulePermissionDao $Dao */
        $Dao = BeanFactory::getBean(ModulePermissionDao::class);

        //新增
        if($attached_permission_item_ids){
            $where = [
                'module_id' =>  $module_item_id,
                'permission_id' =>  $attached_permission_item_ids,
            ];
            $insertData = $Dao->getByWhere($where);

            if($insertData){
                throw new ValidatorException('该套餐已经添加该模块');
            }

            //代表新增
            foreach ($attached_permission_item_ids as $attached_module_item_id){
                //循环插入
                $insertData = [];
                $insertData['item_id'] = create_item_id(uuid());
                $insertData['module_id'] = $module_item_id;
                $insertData['permission_id'] = $attached_module_item_id;
                //直接进行插入
                $Dao->insert($insertData);
            }
        }
        //删除
        if($detached_permission_item_ids){
            //删除不对
            //则进行删除操作
            foreach ($detached_permission_item_ids as $detached_module_item_id){
                $searchWhere = [];
                $searchWhere['module_id'] = $module_item_id;
                $searchWhere['permission_id'] = $detached_module_item_id;
                $searchData = $Dao->getByWhere($searchWhere);
                if($searchData){
                    $Dao->delete($searchData['itemId'], true);
                }else{
                    throw new ValidatorException('不存在模块：'.$detached_module_item_id);
                }
            }
        }

        return ['state' => true];
    }

    /**
     * 根本模块id获取所有权限
     * @param array $data
     * @return array
     * @throws \Swoft\Db\Exception\DbException
     */
    public function modulePermissions(array $data): array{
        //这里需要传递module_id
        $query = ModulePermission::join('tenant_permissions', function (JoinClause $join){
            $join->on('module_permission.permission_id', '=', 'tenant_permissions.item_id')
                ->where('tenant_permissions.frozen_state', '=', '0');
        });

        $query = $query->where(['module_permission.module_id' => $data['module_id']]);

        return $query->get(['tenant_permissions.item_id as itemId', 'tenant_permissions.name', 'tenant_permissions.permission_value as permissionValue', 'tenant_permissions.type',  'tenant_permissions.purpose', 'tenant_permissions.remark'])->toArray();
    }

    /**
     * 根据套餐id获取模块列表
     * @param array $data
     * @return array
     * @throws \Swoft\Db\Exception\DbException
     */
    public function packageModules(array $data): array
    {
        //这里需要传递package_id
        $query = \App\Rpc\Model\Entity\PackageModule::join('module', function (JoinClause $join){
            $join->on('package_module.module_id', '=', 'module.item_id')
                ->where('module.frozen_state', '=', '0');
        });

        $query = $query->where(['package_module.package_id' => $data['package_id']]);

        return $query->get(['module.item_id as itemId', 'module.name', 'module.module_value as moduleValue'])->toArray();
    }

    /**
     * 根据租户id获取套餐列表
     * @param array $data
     * @return array
     * @throws \Swoft\Db\Exception\DbException
     */
    public function tenantPackages(array $data): array
    {
        //这里需要传递package_id
        $query = TenantPackage::join('package', function (JoinClause $join){
            $join->on('tenant_package.package_id', '=', 'package.item_id')
                ->where('package.frozen_state', '=', '0');
        });

        $query = $query->where(['tenant_package.tenant_id' => $data['tenant_id']]);

        return $query->get(['package.item_id as itemId', 'package.name', 'package.description', 'tenant_package.start_at as startAt', 'tenant_package.end_at as endAt'])->toArray();
    }

    /******************************************************end总后台**********************************************************/


    /******************************************************私有方法区*********************************************************/
    /**
     * 处理权限的分发和回收
     * @param array $data
     * @return void
     * @throws \ReflectionException
     * @throws \Swoft\Bean\Exception\ContainerException
     * @throws \Swoft\Db\Exception\DbException
     */
    private function tenantAuth(array $data)
    {
        //auth权限取出来然后再写到租户里边去
        $tenant = $data['tenant']??null;
        if(!$tenant){
            throw new ValidationException('租户不存在');
        }

        $package_id = $data['package_id']??null;
        if(!$package_id){
            throw new ValidationException('套餐不存在');
        }

        //必须带有延期时间
        $package_date = $data['package_date']??null;
        if(!$package_date){
            throw new ValidationException('套餐时间不存在');
        }

        $db_name = $data['db_name']??null;
        if(!$db_name){
            throw new ValidationException('租户数据库不存在');
        }

        //@2根据套餐取出权限
        //用户item_ids
        $package_permissons = $this->getPermissionsByPackage($package_id);

        //@3从租户那里拿出所有权限，组装时间
        $tenant_permissions = DB::table("permissions")->db($db_name)->get()->toArray();
        //取数组
        $tenant_permissions_end = array_column($tenant_permissions, 'end_at', 'item_id');
        $tenant_permissions_start = array_column($tenant_permissions, 'start_at', 'item_id');

        //删除租户数据表
        DB::db($db_name)->statement("Truncate Table permissions");

        //@4权限对比
        //计算时间
        //根据套餐时间计算
        //现在时间
        $now = time();
        foreach ($package_permissons as &$package_permisson){
            $package_permisson['created_at'] = time();
            $package_permisson['updated_at'] = 0;
            $package_permisson['start_at'] = $now;
            $package_permisson['end_at'] = $package_date + $now;

            //todo
            if(isset($tenant_permissions_end[$package_permisson['item_id']])){
                //如果找到那么就要继续进行处理
                //这里判断分为三个部分
                //现在时间 > 结束时间
                if($now < $tenant_permissions_end[$package_permisson['item_id']]){
                    //这里需要 从原先结点去
                    $package_permisson['start_at'] = $tenant_permissions_start[$package_permisson['item_id']];
                    $package_permisson['end_at'] = $package_date + $tenant_permissions_end[$package_permisson['item_id']];
                    //todo
                }
            }
        }

        //@5全部组完数据 然后集体入库
        $result = DB::table('permissions')->db($db_name)->insert($package_permissons);
    }

    /**
     * 根据package_id获取模块
     * @param string $package_id
     * @return array
     */
    private function getModuleByPackaga(string $package_id): array
    {
        //todo 根据package_id获取模块
    }

    /**
     * 根据套餐id获取所有权限
     * @param string $package_id
     * @return array
     * @throws \Swoft\Db\Exception\DbException
     */
    private function getPermissionsByPackage(string $package_id): array
    {
        $query = ModulePermission::join('module', function (JoinClause $join){
                //只取未冻结部分的
                $join->on('module.item_id', '=', 'module_permission.module_id')
                    ->where('module.frozen_state', '=', 0);
            })
            ->join('package_module', function(JoinClause $join){
                //只取未冻结部分的
                $join->on('package_module.module_id', '=', 'module.item_id')
                    ->where('package_module.frozen_state', '=', 0);
            })
            ->join('tenant_permissions', function(JoinClause $join){
                $join->on('tenant_permissions.item_id', '=', 'module_permission.permission_id')
                    ->where('tenant_permissions.frozen_state', '=', 0);
            })
            ->where(['module_permission.frozen_state' => 0, 'package_module.package_id' => $package_id])
            ->select('tenant_permissions.item_id', 'tenant_permissions.name', 'tenant_permissions.permission_value', 'tenant_permissions.type', 'tenant_permissions.purpose', 'tenant_permissions.parent_item_id', 'tenant_permissions.remark')
            ->get();

        return $query->toArray();
    }

    /**
     * 开租户预设角色,绑定人员
     * @param array $data
     * @throws \Swoft\Db\Exception\DbException
     * @throws ValidatorException
     */
    private function tenantRole(array $data){
        //预设角色和权限
        //@1超级管理员权限
        //@2货主 @2-1 客服 @2-2 现场 @2-3 审核 @-4 财务
        //@3车队长
        //@4司机
        //todo

        $tenant = $data['tenant']??null;
        if(!$tenant){
            throw new ValidationException('租户不存在');
        }

        $db_name = $data['db_name']??null;
        if(!$db_name){
            throw new ValidationException('租户数据库不存在');
        }

        //此刻应该还有一个admin账户id
        $super_admin = $data['super_admin']??null;
        if(!$super_admin){
            throw new ValidationException('租户数据库不存在');
        }

        /***************************************************超级管理员*************************************************/
        //@1取出所有权限
        $permissions = DB::table('permissions')->db($db_name)->where(['frozen_state' => 0])->get()->toArray();
        //@2入库super_admin  @1name @2permission_value @3frozen_state @4created_at @5item_id（生成）
        //预设超级管理员，这个把所有的权限都分配进去
        $super_data['item_id'] = create_item_id(uuid());
        $super_data['name'] = '超级管理员';
        $super_data['permission_value'] = 'tenant_admin';
        $super_data['description'] = '租户超级管理员';
        $super_data['frozen_state'] = 0;
        $super_data['created_at'] = time();
        $superRole = DB::table('role')->db($db_name)->insertGetId($super_data);
        //获取角色信息
        $super_role_info = DB::table('role')->db($db_name)->where(['id' => $superRole])->first();
        //到此为止数据完成
        //@3 权限分配到角色 所有权限全都分配到这个角色上边,这里集体入库
        $super_role_permission = [];
        foreach ($permissions as $permission){
            $super_role_permission['item_id'] = create_item_id(uuid());
            $super_role_permission['role_id'] = $super_role_info['item_id'];
            $super_role_permission['permission_id'] = $permission['item_id'];
        }
        //数据组装完成 批量插入
        DB::table('role_permission')->db($db_name)->insert($super_role_permission);
        //@4 角色分配人员
        $role_user_data = [];
        $role_user_data['item_id'] = create_item_id(uuid());
        $role_user_data['role_id'] = $super_role_info['item_id'];
        $role_user_data['user_id'] = $super_admin;
        DB::table('user_role')->db($db_name)->insert($role_user_data);
        //超级管理员处理完毕
        /***************************************************end超级管理员**********************************************/

        //apollo预设好权限
        /***************************************************租户客服预设***********************************************/
        $this->tenantRolePermissions($permissions, $db_name, '租户客服', 'tenant_service', 'tenant_service', 'tenant_service', '客服负责审核工单等功能');
        $this->tenantRolePermissions($permissions, $db_name, '租户主管', 'tenant_service_manager', 'tenant_service_manager', 'tenant_service_manager', '客服主管：管理客服以及工单分配');

        /***************************************************end租户客服预设********************************************/

        /***************************************************start大货主**********************************************/
        $this->tenantRolePermissions($permissions, $db_name, '大货主', 'big', 'big', 'big', '大货主可以创建管理二级货主');
        /***************************************************end大货主**********************************************/

        /***************************************************货主预设***************************************************/
        //预设货主
        //@1name @2permission_value @3frozen_state @4created_at @5item_id（生成）
        $this->tenantRolePermissions($permissions, $db_name, '货主管理员', 'consigner', 'consigner', 'consigner_admin', '管理员主账号：全部菜单下全部功能
');
        //|____客服
//        $this->tenantRolePermissions($permissions, $db_name, '货主客服', 'consigner_service', 'consigner_service', 'consigner_service');
        //|____财务
        $this->tenantRolePermissions($permissions, $db_name, '货主财务', 'consigner_financial', 'consigner_financial', 'consigner_financial', '财务管理的角色：财务管理菜单+发票管理菜单+历史记录');
        //|____现场
        $this->tenantRolePermissions($permissions, $db_name, '货主现场运营', 'consigner_scene', 'consigner_scene', 'consigner_scene', '发单/装货/卸货现场运营：基础设置菜单+运单管理菜单+承运单管理菜单');
        //|____市场
        $this->tenantRolePermissions($permissions, $db_name, '货主接单审核', 'consigner_market', 'consigner_market', 'consigner_market', '司机报名审核角色：承运单菜单下【审核】功能');
        /***************************************************end货主预设************************************************/

        /***************************************************承运商预设***************************************************/
        //预设承运商
        //@1name @2permission_value @3frozen_state @4created_at @5item_id（生成）
        $this->tenantRolePermissions($permissions, $db_name, '承运商管理员', 'carrier', 'carrier', 'carrier_admin', '管理员主账号：全部菜单下全部功能');
        //|____客服
//        $this->tenantRolePermissions($permissions, $db_name, '承运商客服', 'carrier_service', 'carrier_service', 'carrier_service');
        //|____财务
        $this->tenantRolePermissions($permissions, $db_name, '承运商财务', 'carrier_financial', 'carrier_financial', 'carrier_financial', '财务管理的角色：财务管理菜单+发票管理菜单+历史记录');
        //|____现场
        $this->tenantRolePermissions($permissions, $db_name, '承运商现场运营', 'carrier_scene', 'carrier_scene', 'carrier_scene', '发单/装货/卸货现场运营：基础设置菜单+运单管理菜单+承运单管理菜单');
        //|____市场
        $this->tenantRolePermissions($permissions, $db_name, '承运商接单审核', 'carrier_market', 'carrier_market', 'carrier_market', '司机报名审核角色：承运单菜单下【审核】功能');
        /***************************************************end承运商预设************************************************/

        /***************************************************车队长预设*************************************************/
        //车队长
        //@1name @2permission_value @3frozen_state @4created_at @5item_id（生成）
        //车队长权限
        $this->tenantRolePermissions($permissions, $db_name, '车队长', 'captain', 'captain', 'captain_admin', '车队长角色');
        /***************************************************end车队长预设**********************************************/

        /***************************************************代理人预设*************************************************/
        //代理人 暂时不考虑代理人
        //@1name @2permission_value @3frozen_state @4created_at @5item_id（生成）
        //代理人权限
//        $this->tenantRolePermissions($permissions, $db_name, '代理人', 'agent', 'agent', 'agent_admin');
        /***************************************************end代理人预设**********************************************/

        /***************************************************司机预设***************************************************/
        //司机
        //@1name @2permission_value @3frozen_state @4created_at @5item_id（生成）
        $this->tenantRolePermissions($permissions, $db_name, '司机', 'driver', 'driver', 'driver', '司机角色：平台实际承运人');
        /***************************************************end司机预设************************************************/
    }

    /**
     * 这里创建role并且授予权限
     * @param array $permissions
     * @param string $db_name
     * @param string $name
     * @param string $permission_value
     * @param string $config
     * @param string $default
     * @throws \ReflectionException
     * @throws \Swoft\Bean\Exception\ContainerException
     * @throws \Swoft\Db\Exception\DbException
     */
    private function tenantRolePermissions(array $permissions, string $db_name, string $name, string $permission_value, string $config, string $default, string $des = '')
    {
        $sub_permissions = explode(',', config('service.'.$config, $default));

        $role_data['item_id'] = create_item_id(uuid());
        $role_data['name'] = $name;
        $role_data['permission_value'] = $permission_value;
        $role_data['description'] = $des;
        $role_data['frozen_state'] = 0;
        $role_data['created_at'] = time();
        $RoleId = DB::table('role')->db($db_name)->insertGetId($role_data);
        //获取角色信息
        $role_info = DB::table('role')->db($db_name)->where(['id' => $RoleId])->first();
        //处理权限
        $role_permission = [];
        foreach ($permissions as $permission){
            if(in_array($permission['permission_value'], $sub_permissions)){
                $role_permission['item_id'] = create_item_id(uuid());
                $role_permission['role_id'] = $role_info['item_id'];
                $role_permission['permission_id'] = $permission['item_id'];
            }
        }
        //集体入库
        DB::table('role_permission')->db($db_name)->insert($role_permission);
    }

    /**
     * 各个模块的健康情况
     * @param array $data
     * @return array
     * @throws \Swoft\Db\Exception\DbException
     */
    public function moduleHealth(array $data): array{
        //首先得知道tenant_id 租户id

        //查询下租户信息
        /** @var TenantDao $tenantDao */
        $tenantDao = BeanFactory::getBean(TenantDao::class);
        $info = $tenantDao->getByWhere(['item_id' => $data['tenant_id']]);
        if(!$info){
            return [
                'tip' => '租户不存在'
            ];
        }

        /** @var TenantPackageDao $dao */
        $dao = BeanFactory::getBean(TenantPackageDao::class);
        $condition = [
            'where' => ['tenant_id' => $data['tenant_id'], 'frozen_state' => 0],
            'per' => 10000
        ];
        $packageList = $dao->getList($condition);

        //这里取到所有套餐的ids
        $packageIds = array_column($packageList['data'], 'packageId');

        $query = \App\Rpc\Model\Entity\PackageModule::join('module', function (JoinClause $join){
                $join->on('module.item_id', '=', 'package_module.module_id')
                    ->where('module.frozen_state', '=', 0);
            })
            ->whereIn('package_module.package_id', $packageIds)
            ->get([
                'module.item_id as itemId',
                'module.created_at as createdAt',
                'module.frozen_state as frozenState',
                'module.name as name',
                'module.module_value as moduleValue',
            ])->toArray();

        //开始查询数据库是否存在
        foreach ($query as &$item){
            $db_name = env('APP_ENV')."_".$item['moduleValue']."_".$info['prefix'];
            $item['isHasDatabase'] = is_has_database($db_name);
        }

        return $query;
    }

    /**
     * 开始强调
     * @param array $condition
     * @return array
     * @throws \Swoft\Db\Exception\DbException
     */
    public function tenantMemberList(array $condition): array {

        //首先是解析条件
        $p = 1;
        if (isset($condition['page']) && $condition['page'] > 0) {
            $p = intval($condition['page']);
        }
        $per = 10;
        if (isset($condition['pageSize']) && $condition['pageSize'] > 0) {
            $per = intval($condition['pageSize']);
        }

        //解析where
        $where = [];
        if (isset($condition['where'])) {
            $where = $condition['where'];
        }

        //创造查询语句
        $query = User::join('user_role', function (JoinClause $join){
                $join->on('user.item_id', '=', 'user_role.user_id');
            })
            ->join('role', function(JoinClause $join){
                $join->on('user_role.role_id', '=', 'role.item_id');
            });

        //添加条件
        $query = $query->where($where);

        //总数
        $count = $query->count();

        $fields = [
            'user.item_id as itemId',
            'user.account as phone',
            'user.created_at as createdAt',
            'user.frozen_state as frozenState',
            'role.name as roleName',
        ];

        //数据
        $list = $query->forPage($p, $per)->get($fields)->toArray();

        //循环处理一些字段
        foreach ($list as $key => &$item){
            $item['index'] = ($p - 1)*$per+(++$key);
            $item['createdAt'] = $item['createdAt']?date('Y-m-d H:i:s', intval($item['createdAt'])):'';
        }

        return return_list($list, $count, $p, $per);
    }

    /**
     * 角色信息
     * @param array $data
     * @return array
     * @throws \Swoft\Db\Exception\DbException
     */
    public function userRoleInfo(array $data): array {
        $where = [
            'user_id' => $data['user_id']??''
        ];

        //创造查询语句
        $query = UserRole::join('role', function(JoinClause $join){
                $join->on('user_role.role_id', '=', 'role.item_id');
            });

        //添加条件
        $query = $query->where($where);

        $fields = [
            'role.created_at as createdAt',
            'role.frozen_state as frozenState',
            'role.name as roleName',
            'role.permission_value as permissionValue'
        ];

        //数据
        return  $query->firstArray($fields);
    }

    /**
     * 验证密码是否正确
     * @param $data
     * @return array
     */
    public function checkPassword(array $data): array{
        $userModel = User::where(['account'=>$data['account']])->firstArray();
        $checkPasswor = create_password($data['password'],$userModel['salt']);
        if($checkPasswor == $userModel['password']){
            return Response::Info();
        }else{
            return Response::FatalError(500,'密码错误');
        }
    }
    /******************************************************end私有方法区***********************************************/


    /*******************************************************************************************************************
    * 　　　　　　　　┏┓　　　┏┓+ +                                                                                *
    * 　　　　　　　┏┛┻━━━┛┻┓ + +                                                                             *
    * 　　　　　　　┃　　　　　　　┃                                                                                 *
    * 　　　　　　　┃　　　━　　　┃ ++ + + +                                                                        *
    * 　　　　　　 ████━████ ┃+                                                                              *
    * 　　　　　　　┃　　　　　　　┃ +                                                                               *
    * 　　　　　　　┃　　　┻　　　┃                                                                                 *
    * 　　　　　　　┃　　　　　　　┃ + +                                                                             *
    * 　　　　　　　┗━┓　　　  ┏━┛                                                                               *
    * 　　　　　　　　　┃　　　┃                                                                                     *
    * 　　　　　　　　　┃　　　┃ + + + +                                                                             *
    * 　　　　　　　　　┃　　　┃　　　　 Code is far away from bug with the animal protecting                        *
    * 　　　　　　　　　┃　　　┃ + 　　　　神兽保佑,代码无 bug                                                       *
    * 　　　　　　　　　┃　　　┃                                                                                     *
    * 　　　　　　　　　┃　　　┃　　+                                                                                *
    * 　　　　　　　　　┃　 　　┗━━━┓ + +                                                                        *
    * 　　　　　　　　　┃ 　　　　　　　┣┓                                                                          *
    * 　　　　　　　　　┃ 　　　　　　　┏┛                                                                          *
    * 　　　　　　　　　┗┓┓┏━┳┓┏┛ + + + +                                                                     *
    * 　　　　　　　　　　┃┫┫　┃┫┫                                                                               *
    * 　　　　　　　　　　┗┻┛　┗┻┛+ + + +                                                                        *
    *******************************************************************************************************************/
}
